﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;

namespace Clipboard.Tools
{
    public class Cryptography
    {
        // AES Encryption and Decryption
        // 创建一个随机数生成器实例，用于生成盐值和其他随机数据
        private static readonly RandomNumberGenerator rng = RandomNumberGenerator.Create();
        // AES密钥大小，以位为单位（AES-256使用256位密钥）
        private const int KeySize = 256;
        // AES的初始化向量（IV）大小，以字节为单位（AES块大小为128位，即16字节）
        private const int IvSize = 128 / 8;

        /// <summary>
        /// 使用AES算法和提供的密码加密字符串。
        /// </summary>
        /// <param name="plainText">要加密的明文。</param>
        /// <param name="password">用于生成密钥的密码。</param>
        /// <returns>包含加密字符串、密钥和IV的元组。</returns>
        public static (string Encrypted, string Key, string Iv) EncryptString(string plainText, string password)
        {
            // 生成一个随机盐值，用于增强密钥的安全性
            byte[] salt = GenerateRandomSalt();

            // 创建一个AES算法实例
            using (Aes aesAlg = Aes.Create())
            {
                // 使用盐值和密码生成密钥和IV
                using (Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, salt))
                {
                    aesAlg.Key = key.GetBytes(KeySize / 8); // 获取密钥
                    aesAlg.IV = key.GetBytes(IvSize); // 获取IV
                }

                // 创建一个加密器
                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                // 使用内存流和加密流将明文加密为密文
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    msEncrypt.Write(salt, 0, salt.Length); // 将盐值写入密文开头
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        swEncrypt.Write(plainText); // 写入明文
                    }
                    byte[] encrypted = msEncrypt.ToArray(); // 获取完整的密文（包括盐值）
                                                            // 返回加密后的字符串、密钥和IV（以Base64编码）
                    return (Convert.ToBase64String(encrypted), Convert.ToBase64String(aesAlg.Key), Convert.ToBase64String(aesAlg.IV));
                }
            }
        }

        /// <summary>
        /// 使用AES算法和提供的密码解密字符串。
        /// </summary>
        /// <param name="cipherText">要解密的密文（包括盐值）。</param>
        /// <param name="password">用于生成密钥的密码。</param>
        /// <returns>解密后的明文。</returns>
        public static string DecryptString(string cipherText, string password)
        {
            // 将密文从Base64编码转换为字节数组
            byte[] fullCipher = Convert.FromBase64String(cipherText);

            // 使用内存流读取密文
            using (MemoryStream msDecrypt = new MemoryStream(fullCipher))
            {
                byte[] salt = new byte[32]; // 假设盐值大小为32字节（256位）
                msDecrypt.Read(salt, 0, salt.Length); // 读取盐值

                // 创建一个AES算法实例
                using (Aes aesAlg = Aes.Create())
                {
                    // 使用盐值和密码生成密钥和IV
                    using (Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, salt))
                    {
                        aesAlg.Key = key.GetBytes(KeySize / 8); // 获取密钥
                        aesAlg.IV = key.GetBytes(IvSize); // 获取IV
                    }

                    // 创建一个解密器
                    ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                    // 使用解密流和读取器将密文解密为明文
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                    {
                        return srDecrypt.ReadToEnd(); // 返回解密后的明文
                    }
                }
            }
        }

        /// <summary>
        /// 使用SHA256算法计算字符串的哈希值。
        /// </summary>
        /// <param name="rawData">要计算哈希值的原始字符串。</param>
        /// <returns>SHA256哈希值的十六进制字符串表示。</returns>
        public static string ComputeSha256Hash(string rawData)
        {
            // 创建一个SHA256哈希算法实例
            using (SHA256 sha256Hash = SHA256.Create())
            {
                // 将原始字符串转换为字节数组，并计算哈希值
                byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));

                // 将字节数组转换为十六进制字符串
                StringBuilder builder = new StringBuilder();
                for (int i = 0; i < bytes.Length; i++)
                {
                    builder.Append(bytes[i].ToString("x2")); // 每个字节转换为两位十六进制数
                }
                return builder.ToString(); // 返回哈希值的十六进制字符串
            }
        }

        /// <summary>
        /// 生成一个随机盐值。
        /// </summary>
        /// <returns>随机生成的盐值字节数组。</returns>
        private static byte[] GenerateRandomSalt()
        {
            byte[] salt = new byte[32]; // 创建一个32字节（256位）的数组来存储盐值
            rng.GetBytes(salt); // 使用随机数生成器填充盐值数组
            return salt; // 返回生成的盐值
        }
    }
}
